
<template>
  <div class="formrules">
    <slot name="items"></slot>
  </div>
</template>
<script>
/**
 * author：ronggang
 * email：suntework@163.com
 */
export default {
  name: "vant-form",
  data() {
    return {
      rulesEles: []
    };
  },
  props: ["inputVail", "rules"],
  mounted() {
    // 递归获取所有带有 rule 属性的元素
    this.rulesEles = this.getRuleEle(this.$slots.items);
    // 处理 输入监听的校验
    if (this.inputVail) this.eleSetInput();
  },
  methods: {
    // 递归获取插槽内所有拥有 input 属性的元素【内部方法】
    getRuleEle(eleObj) {
      let self = this,
        childs = [];
      if (!eleObj) return;
      // 循环所有元素（兼容 对象和数组的情况）
      for (let i in eleObj instanceof Array ? eleObj : [eleObj]) {
        let ele = eleObj[i];
        // 当前元素包含 rule 属性，则收录起来
        if (ele.data && ele.data.attrs["rule"]) {
          ele.elm.getElementsByClassName(
            "van-field__error-message"
          )[0].style.display = "none";
          childs.push(ele);
        }
        // 当前元素存在子元素，则递归查询
        ele.children &&
          childs.push.apply(childs, this.getRuleEle(ele.children));
      }
      return childs;
    },
    // 设置 需要校验的属性 的 input监听 校验 【内部方法】
    eleSetInput() {
      let self = this;
      try {
        for (let i in self.rulesEles) {
          (function(index) {
            // 获取元素下 input 元素（目前只针对 单个输入框做处理）
            let inputEle = self.rulesEles[index].elm.getElementsByTagName(
              "input"
            )[0];
            inputEle.oninput = function() {
              // 输入实时校验
              self.handleVail(index);
            };
          })(i);
        }
      } catch (e) {
        console.error("vail error：" + e);
      }
    },
    // 检验元素的值是否满足条件（参数：索引值 ）【内部方法】
    handleVail(i) {
      try {
        let self = this,
          handleEle = self.rulesEles[i];
        // 获取元素下 input 元素（目前只针对 单个输入框做处理）
        let inputValue = handleEle.elm.getElementsByTagName("input")[0].value,
          vailFlag = true;
        // 获取设置的校验规则
        let ruleObj = self.rules
          ? self.rules[handleEle.data.attrs["rule"]]
          : null;
        if (!ruleObj) return vailFlag;
        // 非空校验
        vailFlag = ruleObj.required ? !!inputValue : vailFlag;
        // 正则校验
        vailFlag = ruleObj.regExp
          ? ruleObj.regExp.test(inputValue) && vailFlag
          : vailFlag;
        // 用户自定义校验
        vailFlag =
          typeof ruleObj.handleVailFun === "function"
            ? ruleObj.handleVailFun(inputValue) && vailFlag
            : vailFlag;
        // 获取组件实例，修改错误信息(注释的代码可以实现效果，但是违反了子组件修改父组件的规则)
        // handleEle.componentInstance.errorMessage = vailFlag?'':ruleObj.errorMessage;
        //目前是通过控制元素显示隐藏去实现错误信息的展示
        if (!vailFlag)
          self.rulesEles[i].elm.getElementsByClassName(
            "van-field__error-message"
          )[0].style.display = "block";
        else
          self.rulesEles[i].elm.getElementsByClassName(
            "van-field__error-message"
          )[0].style.display = "none";
        return vailFlag;
      } catch (e) {
        console.error("vail error：" + e);
      }
    },
    // 整体校验【对外提供方法】
    allVail() {
      let self = this,
        vailFlag = true;
      for (let i in this.rulesEles) {
        vailFlag = !self.handleVail(i) ? false : vailFlag && true;
      }
      return vailFlag;
    }
  }
};
</script>
<style>
.formrules {
  height: 100%;
}
</style>
